function defineReactive(obj,key,val) {
    var dep=new Dep();
    Object.defineProperty(obj,key,{
        get:function () {
            //添加订阅者watcher到主题对象Dep
            if(Dep.target) dep.addSub(Dep.target);
            return val;
        },
        set:function (newVal) {
            if(newVal===val) return
            val=newVal;
            //console.log(val);
            dep.notify();
        }
    })
}

function observe(obj,vm) {
    Object.keys(obj).forEach(function (t) {
        defineReactive(vm,t,obj[t])
    });
}

function compile(node,vm) {
    var reg=/\{\{(.*)\}\}/;
    //节点类型为元素
    if(node.nodeType==1){
        var attr=node.attributes;
        //解析属性
        for(var i=0;i<attr.length;i++){
            if(attr[i].nodeName=='v-model'){
                var name=attr[i].nodeValue;//获取v-model绑定的属性名
                node.addEventListener('input',function (e) {
                    //给相应的data属性赋值,进而触发该属性的set方法
                    vm[name]=e.target.value;
                })
                node.value=vm[name];//将data值赋给该Node
                node.removeAttribute('v-model');
            }

        }

    }
    //节点类型为text
    if(node.nodeType==3){

        if(reg.test(node.nodeValue)){
            var name=RegExp.$1;//获取匹配到的字符串
            name=name.trim();
          //  node.nodeValue=vm[name];//将data的值赋给该node
            new Watcher(vm,node,name);
        }

    }

}

function Watcher(vm,node,name) {
    Dep.target=this;
    this.name=name;
    this.node=node;
    this.vm=vm;
    this.update();
    Dep.target=null;
}

Watcher.prototype={
    update:function () {
        this.get();
        this.node.nodeValue=this.value;
    },
    //获取data中的属性值
    get:function(){
        this.value=this.vm[this.name];//触发相应属性的get
    }

}


function nodeToFragment(node,vm) {
    var flag=document.createDocumentFragment();
    var child;
    while (child=node.firstChild){
        compile(child,vm);
        flag.append(child); //将子节点劫持到文档片段中
    }
    return flag;
}

function Dep() {
    this.subs=[]
}
Dep.prototype={
    addSub:function (sub) {
        this.subs.push(sub);
    },
    notify:function () {
        this.subs.forEach(function (t) { t.update() });
    }
}

function Vue(options) {
    this.data=options.data;
    var data=this.data;
    observe(data,this.data);

    var id=options.el;
    var dom=nodeToFragment(document.getElementById(id),this.data);
    //编译完成后，将dom返回到app中
    document.getElementById(id).appendChild(dom);


}